#!/usr/bin/perl -w
###############################################################################
# $Id: vcl.pm 1075500 2012-04-08 19:22:55Z stallam $
###############################################################################
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
###############################################################################
=head1 NAME

VCL::Provisioning::ec2 - VCL module to support povisioning of EC2 machines on other cloud

=head1 SYNOPSIS

 Needs to be written

=head1 DESCRIPTION

 This module provides provisioning source to provision machines on EC2 cloud

=cut

##############################################################################

package VCL::Module::Provisioning::ec2;

# Specify the lib path using FindBin
use FindBin;
use lib "$FindBin::Bin/../../..";

# Configure inheritance
use base qw(VCL::Module::Provisioning);

# Specify the version of this module
our $VERSION = '2.2.1';

# Specify the version of Perl to use
use 5.008000;

use strict;
use warnings;
use diagnostics;
use English qw( -no_match_vars );
use Scalar::Util;
use VCL::utils;
use Fcntl qw(:DEFAULT :flock);
# Specify lib for EC2 module
use Digest;
use Digest::SHA qw(hmac_sha256_base64);
use URI::Escape qw(uri_escape_utf8);
use Data::Dumper;
use XML::Simple;

$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME}=0;

##############################################################################
=head1 OBJECT METHODS

=cut

#/////////////////////////////////////////////////////////////////////////////

=head2 capture

 Parameters  : $request_data_hash_reference
 Returns     : 1 if sucessful, 0 if failed
 Description : Saves the image back into the repository.

=cut
sub rnotify {
	my $log_message = shift;
	open(OUTPUT, ">>", "/usr/local/vcl/lib/VCL/Module/Provisioning/log");
	print OUTPUT "$log_message\n";
	close OUTPUT;
}
sub capture {
	rnotify("VCL, should I support capturing an image?");
	return 1;
} ## end sub capture

sub initialize{
	notify($ERRORS{'DEBUG'}, 0, "EC2 module initialized");
	return 1;
}
#/////////////////////////////////////////////////////////////////////////////

sub brokerRequest {
    my $instanceID = $_[0];
    my $start = $_[1];
    my $len = $_[2];
	my $reservationid = $_[3];
	my $request_id = $_[4];
	my $db_img_id = $_[5];
	my $serverip = $_[6];
	my $user = $_[7];
	my $passwd = $_[8];
	rnotify("image id : $db_img_id");
	rnotify("start : $start");
	rnotify("len: $len");
	rnotify("reservation id : $reservationid");
	my @result = ($serverip, $user, $passwd);
	rnotify(format_data(@result));
	#update computer table, reservation table and new vclinstances table
	return updateDatabaseEntries($reservationid, $instanceID, $serverip, $user, $passwd, $request_id, $db_img_id);
}
#/////////////////////////////////////////////////////////////////////////////
=head2 provision

 Parameters  : hash
 Returns     : 1(success) or 0(failure)
 Description : loads node with provided image.  This includes, setting up any files (copying or registering).  Loading the resource.  Turn on the resource.  Wait until the resource is ready to use (after the vm or physical machine has booted).
In terms of EC2, we fire an API request for "startInstance" for the instanceID, and wait until the EC2 cloud returns some status for the request.

Note: allow computer to load only for state = new, for rest just return 1.

=cut

sub load {
	my $self = shift;
	if (ref($self) !~ /ec2/i) {
		rnotify("subroutine was called as a function, it must be called as a class method");
		return 0;
	}
	my ($package, $filename, $line, $sub) = caller(0);
	rnotify("ec2.pm, the load method has been successfully called");
	my $request_state_name = $self->data->get_request_state_name();
	rnotify("request state name : $request_state_name");
	my $request_id = $self->data->get_request_id();
	rnotify("request id : $request_id");
	if ($request_state_name ne 'new') {

		#return 1;
		# It is not new.Delete tables.
		$request_id = $request_id - 1;
		my $select_statement = "SELECT instanceid FROM ec2instances WHERE requestid=$request_id";
		my @selected_rows = database_select($select_statement);
    		# Check to make sure 1 row was returned
    		if (scalar @selected_rows == 0) {
			rnotify("failed to get instanceid of reservation");
			return 1;
    		}
     		my $instanceid = $selected_rows[0]{instanceid};
		rnotify("Instance ID: $instanceid");
		# Stop instance
		stopInstance($instanceid);
	 	my $brokerinstance_update = "UPDATE ec2BrokeredInstances SET status=0 WHERE instanceid = \'$instanceid\'";
		# Call the database execute subroutine
	        if (database_execute($brokerinstance_update)) {
        	       rnotify("ec2BrokeredInstances is updated");
        	}
        	else {
                	rnotify("unable to update ec2BrokeredInstances");
			return 1;
        	}

		my $deleteInstance = "DELETE FROM ec2instances WHERE instanceid=\'$instanceid\'";
		# Call the database execute subroutine
        	if (database_execute($deleteInstance)) {
        	       	rnotify("deleted from ec2instances");
        	}
        	else {
                	rnotify("unable to deletet from ec2instances");
			return 1;
        	}
		return 1;
	}	

	# Store some hash variables into local variables


	my $reservation_id = $self->data->get_reservation_id();
	my $image_id = $self->data->get_image_id();
	rnotify("image id: $image_id");
	#get imageid on another cloud for given imagename
        my $select_statement = "select instanceid AS instance_ids from ec2BrokeredInstances where ami_id=(select amiid from ec2Image where imageid=$image_id)";
        my @selected_rows = database_select($select_statement);
        if (scalar @selected_rows == 0) {
               rnotify("Empty rows selected");
               return -1;
        }
	my $instanceID = "";
        for (@selected_rows) {
               my %image_row = %{$_};
               $instanceID = $image_row{instance_ids};
        }

	my $start_time = $self->data->get_request_start_time(0);
	my $end_time = $self->data->get_request_end_time(0);
	my $user = $self->data->get_user_login_id();
	rnotify("user logged in: $user");
	rnotify("start time : $start_time");
	rnotify("end time: $end_time");
	#get password of corresponding user
	my $passwd = getPassword($user);
	rnotify("password: $passwd");
	my $startepoch = convert_to_epoch_seconds($start_time);
	my $currepoch = time();
	if ($startepoch <= $currepoch) {
		$startepoch = $currepoch;
	}
        my $endepoch = convert_to_epoch_seconds($end_time);
        my $len  = ($endepoch - $startepoch)/60; #api needs in minutes
	rnotify("start epoch time : $startepoch");
        rnotify("end epoch time: $endepoch");

	#retrieve IPaddress of vm - start ec2 vm and retreive ip address
	my $ipaddress = getCloudAddress($instanceID,$user,$passwd);
	if($ipaddress eq ""){
		rnotify("Unable to load resources or resource currently unavailable.");
		return 0;
	}
	rnotify("cloud address $ipaddress");

	my $status = brokerRequest($instanceID, $startepoch, $len, $reservation_id, $request_id, $image_id,$ipaddress,$user,$passwd);
	if ($status == 1){
		return 1;
	} else { 
		return 0;
	}
		
} ## end sub load
#/////////////////////////////////////////////////////////////////////////////

sub generate_timestamp {
	# EC2 compatible timestamp creation.
    return sprintf("%04d-%02d-%02dT%02d:%02d:%02d.000Z",
       sub {    ($_[5]+1900,$_[4]+1,$_[3],$_[2],$_[1],$_[0])
           }->(gmtime(time)));
}
#/////////////////////////////////////////////////////////////////////////////

sub startInstance{
	my $EC2_ACCESS_KEY='';
	my $EC2_SECRET_KEY='';
	my $EC2_URL='';
	my $instance_Id = $_[0];
	if ($ENV{'EC2_ACCESS_KEY'}) {
		$EC2_ACCESS_KEY = $ENV{'EC2_ACCESS_KEY'};
	} else {
		#die "EC2_ACCESS_KEY environment variable must be set.";
		$EC2_ACCESS_KEY = getAWSKEY();
	};

	if ($ENV{'EC2_SECRET_KEY'}) {
		$EC2_SECRET_KEY = $ENV{'EC2_SECRET_KEY'};
	} else {
		#die "EC2_SECRET_KEY environment variable must be set.";
		$EC2_SECRET_KEY = getAWSSECRET($EC2_ACCESS_KEY);
	};

	if ($ENV{'EC2_URL'}) {
		$EC2_URL = $ENV{'EC2_URL'};
	} else {
		#die "EC2_URL environment variable must be set.";
		$EC2_URL = 'https://ec2.amazonaws.com/';
	};

	# Pull the host and path out of EC2_URL, since we need them for signing.
	my $EC2_HOST='';
	my $EC2_PATH='';
	if ($EC2_URL =~ /\/\/([^\/]+)(.*)$/) {
		$EC2_HOST = $1;
		if ($2) {
			$EC2_PATH = $2;
		} else {
			$EC2_PATH = "/";
		};
	};
	#undef @actions;
	my @actions;
	my $arg="Action=StartInstances";
	push (@actions, $arg);
	#$instance_Id="i-57423d33";
	$arg="InstanceId=$instance_Id";
	push (@actions, $arg);
	# Generate our timestamp for request signing.

	my $timestamp = generate_timestamp();

	# Add the required variables to complete request signing to the actions list.
	# In the future we should let the user override.

	push (@actions, "SignatureMethod=HmacSHA256", "SignatureVersion=2",
					"Version=2011-05-15", "AWSAccessKeyId=$EC2_ACCESS_KEY",
					"Timestamp=$timestamp");
	#undef @clean_actions;
	my @clean_actions;
	# Process the actions list to escape bad characters in names and values.
	my $x;
	my $y;
	#undef $action;
	my $action;
	foreach $action (@actions) {
		($x,$y) = split(/\=/,$action,2);
		$x = uri_escape_utf8($x);
		$y = uri_escape_utf8($y);
		push (@clean_actions,"$x=$y");
	};

	# Sort them for signing purposes.
	@clean_actions = sort(@clean_actions);

	# Create the query string for signing.
	my $query = join ("&", @clean_actions);

	# Sign the query string.
	my $sig = uri_escape_utf8(hmac_sha256_base64("GET\n$EC2_HOST\n$EC2_PATH\n$query",
						   $EC2_SECRET_KEY));

	# Add the signature to the end of the request url.
	push (@clean_actions,"Signature=$sig=");

	# Re-create the query string with the signature included.
	$query = join ("&", @clean_actions);
#	rnotify($query);
	my $resp = `curl -s \"$EC2_URL?$query\" 2>&1 | xmllint --format -`;
#	rnotify($resp);

} ## end sub startInstance
#/////////////////////////////////////////////////////////////////////////////

sub getIPAddress{
	my $instance_Id = $_[0];
	my $user = $_[1];
	my $pass = $_[2];
	
	my $EC2_ACCESS_KEY='';
	my $EC2_SECRET_KEY='';
	my $EC2_URL='';
	# Get values from environment variables.
	
	if ($ENV{'EC2_ACCESS_KEY'}) {
		$EC2_ACCESS_KEY = $ENV{'EC2_ACCESS_KEY'};
	} else {
		#die "EC2_ACCESS_KEY environment variable must be set.";
		$EC2_ACCESS_KEY = getAWSKEY();
	};

	if ($ENV{'EC2_SECRET_KEY'}) {
		$EC2_SECRET_KEY = $ENV{'EC2_SECRET_KEY'};
	} else {
		#die "EC2_SECRET_KEY environment variable must be set.";
		$EC2_SECRET_KEY = getAWSSECRET($EC2_ACCESS_KEY);
	};

	if ($ENV{'EC2_URL'}) {
		$EC2_URL = $ENV{'EC2_URL'};
	} else {
		#die "EC2_URL environment variable must be set.";
		$EC2_URL = 'https://ec2.amazonaws.com/';
	};
	
	my $EC2_HOST = '';
	my $EC2_PATH = '';
	if ($EC2_URL =~ /\/\/([^\/]+)(.*)$/) {
		$EC2_HOST = $1;
		if ($2) {
			$EC2_PATH = $2;
		} else {
			$EC2_PATH = "/";
		};
	};
	#undef @actions;
	my @actions;
	my $arg="Action=DescribeInstances";
	push (@actions, $arg);
	#$instance_Id="i-57423d33";
	$arg="InstanceId.1=$instance_Id";
	push (@actions, $arg);
	# Generate our timestamp for request signing.

	my $timestamp = generate_timestamp();

	# Add the required variables to complete request signing to the actions list.
	# In the future we should let the user override.

	push (@actions, "SignatureMethod=HmacSHA256", "SignatureVersion=2",
					"Version=2011-05-15", "AWSAccessKeyId=$EC2_ACCESS_KEY",
					"Timestamp=$timestamp");

	# Process the ctions list to escape bad characters in names and values.
	#undef @clean_actions;
	my @clean_actions;
	my $x;
	my $y;
	#undef $action;
	my $action;
	foreach $action (@actions) {
		($x,$y) = split(/\=/,$action,2);
		$x = uri_escape_utf8($x);
		$y = uri_escape_utf8($y);
		push (@clean_actions,"$x=$y");
	};

	# Sort them for signing purposes.
	@clean_actions = sort(@clean_actions);
	
	# Create the query string for signing.
	my $query = join ("&", @clean_actions);

	# Sign the query string.
	my $sig = uri_escape_utf8(hmac_sha256_base64("GET\n$EC2_HOST\n$EC2_PATH\n$query",
						   $EC2_SECRET_KEY));

	# Add the signature to the end of the request url.
	push (@clean_actions,"Signature=$sig=");

	# Re-create the query string with the signature included.
	$query = join ("&", @clean_actions);

	my $tries = 240;
	while($tries > 0)
	{
		my $resp = `curl -s \"$EC2_URL?$query\" 2>&1 | xmllint --format -`;

		my $xml = new XML::Simple;
		my $data = $xml->XMLin($resp);
		#rnotify("Trying to find IP Address!!");
		#rnotify($resp);
		if($resp =~m/<ipAddress>/i){
			my $ipaddress =  $data->{reservationSet}->{item}->{instancesSet}->{item}->{ipAddress};
			my $hostName = $data->{reservationSet}->{item}->{instancesSet}->{item}->{dnsName};
			setupEnvironment($instance_Id, $hostName,$user,$pass);
			return $ipaddress;
		}
		$tries = $tries -5;
		sleep 5;
	}
	return "";
}## end of getIPAddress
#/////////////////////////////////////////////////////////////////////////////

sub create_ssh_file{
	my $userName = $_[0];
	open (MYFILE, '>/var/tmp/configure_sshd.pl');
	print MYFILE '#! /usr/bin/perl -w'."\n";;
	print MYFILE 'open (IN, "+< /etc/ssh/sshd_config");'."\n";
	print MYFILE '@file = <IN>;'."\n";
	print MYFILE "seek IN,0,0;\n";
	print MYFILE 'foreach $file (@file){'."\n";
	print MYFILE '$file =~ s/PasswordAuthentication no/PasswordAuthentication yes/;'."\n";
	print MYFILE 'print IN $file;'."\n".'}'."\n";

	print MYFILE "close IN;\n";
	print MYFILE 'open (MYFILE, \'>>/etc/ssh/sshd_config\');'."\n";
	print MYFILE "print MYFILE \"AllowUsers $userName ec2-user\\n\";\n";
	print MYFILE "close (MYFILE);";

	close (MYFILE);	
}

#/////////////////////////////////////////////////////////////////////////////
sub setupEnvironment{
	my $host_name = $_[1];
	my $user = $_[2];
	my $pass = $_[3];
	
	## Need to read from database..
	my $password=crypt($pass,12);

	create_ssh_file($user);
	rnotify("Setting up environment!");
	rnotify("host_name:".$host_name);
	my $connectString = 'ec2-user@'.$host_name;
	
	sleep 120;
	my $command1='ssh -i /var/tmp/cloud_team5.pem '.$connectString.' -t sudo useradd '.$user.' -p '.$password;
	rnotify("Command:".$command1);
	#my $com1 = 'sudo useradd '.$user.' -p '.$password;
	#run_ssh_command($host_name,'/var/tmp/cloud_team5.pem',$com1,'ec2-user');
	system($command1);
	#my $op = `$command1`;
	#rnotify($op);

	my $command2='scp -i /var/tmp/cloud_team5.pem /var/tmp/configure_sshd.pl '.$connectString.':/tmp/configure_sshd.pl';
	#my $op1 = `$command2`;
	system($command2);
	#rnotify($op1);

	#my $com3 = 'sudo cp /etc/ssh/sshd_config /etc/sshd_config_original';
	#run_ssh_command($host_name,'/var/tmp/cloud_team5.pem',$com3,'ec2-user');

	my $command3='ssh -i /var/tmp/cloud_team5.pem '.$connectString.' -t sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config_original';
	#my $op2=`$command3`;
	#rnotify($op2);
	system($command3);
	#my $com4 = 'sudo perl /tmp/configure_sshd.pl';
	#run_ssh_command($host_name,'/var/tmp/cloud_team5.pem',$com4,'ec2-user');


	my $command4='ssh -i /var/tmp/cloud_team5.pem '.$connectString.' -t sudo perl /tmp/configure_sshd.pl';
	#my $op4 = `$command4`;
	#rnotify($op4);
	system($command4);

	#my $com5 = 'sudo chown '.$user.' /home/'.$user;
	#run_ssh_command($host_name,'/var/tmp/cloud_team5.pem',$com5,'ec2-user');
	my $command5='ssh -i /var/tmp/cloud_team5.pem '.$connectString.' -t sudo chown '.$user.' /home/'.$user;
	#my $op5 = `$command5`;
	#rnotify($op5);
	system($command5);


	my $command6='scp -i /var/tmp/cloud_team5.pem /var/tmp/runsshdrestart.pl '.$connectString.':/tmp/runsshdrestart.pl';
	#my $op6=`$command6`;
	system($command6);
	#rnotify($op6);

#       my $com6 = 'sudo perl /tmp/runsshdrestart.pl';
#       run_ssh_command($host_name,'/var/tmp/cloud_team5.pem',$com6,'ec2-user');
	my $command7='ssh -i /var/tmp/cloud_team5.pem '.$connectString.' -t sudo perl /tmp/runsshdrestart.pl';
	#my $op7=`$command7`;
	#rnotify($op7);
	system($command7);
	


} ## end of setupEnvironment
#/////////////////////////////////////////////////////////////////////////////

sub getCloudAddress {
	my $instanceID = $_[0];
	my $user = $_[1];
	my $pass = $_[2];
	startInstance($instanceID);
	my $cloudip = getIPAddress($instanceID,$user,$pass);
	return $cloudip;
}

#/////////////////////////////////////////////////////////////////////////////

sub getPassword {
	my $user = shift;
        #select statement
        my $stmt = "SELECT password FROM users where user='$user'";
        my @selected_rows = database_select($stmt);
        # Check to make sure 1 row was returned
        if (scalar @selected_rows == 0) {
                return 1;
        }
        elsif (scalar @selected_rows > 1) {
                return 0;
        }
        my $password = $selected_rows[0]{password};
        return $password;
}

#/////////////////////////////////////////////////////////////////////////////
sub updateDatabaseEntries {
	my $reservationid = $_[0];
	my $instanceID = $_[1];
	my $serverip = $_[2];
	my $user = $_[3];
	my $passwd = $_[4];
	my $request_id = $_[5];
	my $db_img_id = $_[6];
	rnotify("reservation id : $reservationid");
	rnotify("instance id : $instanceID");	
	rnotify("server i : $serverip");
	rnotify("user id : $user");
	rnotify("password : $passwd");
	rnotify("request id in this cloud : $request_id");
	#update ec2BrokeredInstances table
	my $brokeredInstances_update = " UPDATE ec2BrokeredInstances SET status = 1 WHERE instanceid = '$instanceID' ";
        # Call the database execute subroutine
        if (database_execute($brokeredInstances_update)) {
               rnotify("brokeredInstances status for instanceid is updated");
        }
        else {
                rnotify("unable to update status");
		return -1;
        }
	
	#update reservation table
	my $reservation_update = " UPDATE reservation SET remoteIP = \'$serverip\', pw =\'$passwd\'  WHERE id = $reservationid ";
        # Call the database execute subroutine
        if (database_execute($reservation_update)) {
               rnotify("reservationid is updated");
        }
        else {
                rnotify("unable to update reservationid");
		return -1;
        }
	#select computerid for given reservation id
	my $select_statement = "SELECT computerid FROM reservation WHERE id = $reservationid";
	my @selected_rows = database_select($select_statement);
        # Check to make sure 1 row was returned
        if (scalar @selected_rows == 0) {
		rnotify("failed to get computerid from reservation");
		return -1;
        }
        elsif (scalar @selected_rows > 1) {
		return -1;
        }
        my $computerid = $selected_rows[0]{computerid};
	#update computer table
	my $computer_update = "UPDATE computer set IPaddress = \'$serverip\' WHERE id = $computerid";
	# Call the database execute subroutine
        if (database_execute($computer_update)) {
               rnotify("computerid is updated");
        }
        else {
                rnotify("unable to update computerid");
		return -1;
        }
	#update ec2instances table
	my $vcl_update = "INSERT INTO ec2instances(instanceid, computerid, imageid, reservationid,requestid, username) VALUES('$instanceID', $computerid, $db_img_id, $reservationid, $request_id, \'$user\')";
	# Call the database execute subroutine
        if (database_execute($vcl_update)) {
               rnotify("ec2instances is updated");
        }
        else {
                rnotify("unable to update ec2instances");
		return -1;
        }
	return 1;
}
sub node_status {
	my $self = shift;

	# Check if subroutine was called as a class method
	if (ref($self) !~ /ec2/i) {
		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
		return 0;
	}

	#my ($vmhash) = shift;

	my ($package, $filename, $line, $sub) = caller(0);

	# try to contact vm
	# $self->data->get_request_data;
	# get state of vm
	#my $vmpath             = $self->data->get_vmhost_profile_vmpath;
	#my $datastorepath      = $self->data->get_vmhost_profile_datastore_path;
	#my $requestedimagename = $self->data->get_image_name;
	#my $vmhost_type        = $self->data->get_vmhost_type;
	#my $vmhost_hostname    = $self->data->get_vmhost_hostname;
	#my $vmhost_imagename   = $self->data->get_vmhost_image_name;
	#my $vmclient_shortname = $self->data->get_computer_short_name;
	#my $request_forimaging              = $self->data->get_request_forimaging();

	#notify($ERRORS{'OK'}, 0, "Entering node_status, checking status of $vmclient_shortname");
	#notify($ERRORS{'DEBUG'}, 0, "request_for_imaging: $request_forimaging");
	#notify($ERRORS{'DEBUG'}, 0, "requeseted image name: $requestedimagename");

	my ($hostnode, $identity);

	# Create a hash to store status components
	my %status;

	# Initialize all hash keys here to make sure they're defined
	$status{status}       = 0;
	$status{currentimage} = 0;
	$status{ping}         = 0;
	$status{ssh}          = 0;
	$status{vmstate}      = 0;    #on or off
	$status{image_match}  = 0;

	#$status{status} = 'READY';
	#$status{status} = 'RELOAD';

	notify($ERRORS{'DEBUG'}, 0, "status set to $status{status}");

	notify($ERRORS{'DEBUG'}, 0, "returning node status hash reference (\$node_status->{status}=$status{status})");
	return \%status;

} ## end sub node_status
#/////////////////////////////////////////////////////////////////////////////

sub does_image_exist {
	return 1;

} ## end sub does_image_exist
#/////////////////////////////////////////////////////////////////////////////

sub getAWSKEY {
        #select statement
        my $stmt = "SELECT pub_key FROM provkeys LIMIT 1";
        my @selected_rows = database_select($stmt);
        # Check to make sure 1 row was returned
        if (scalar @selected_rows == 0) {
                return 'AKIAJOWEQSVMR4EJ7N7Q';
        }
        my $awskey = $selected_rows[0]{pub_key};
        return $awskey;
}

#/////////////////////////////////////////////////////////////////////////////

sub getAWSSECRET {
		my $awskey = shift;
        #select statement
        my $stmt = "SELECT pri_key FROM provkeys WHERE pub_key='$awskey'";
        my @selected_rows = database_select($stmt);
        # Check to make sure 1 row was returned
        if (scalar @selected_rows == 0) {
                return 'sY3S+6M0zh4TSMaoLSY6dmqULHD8jsk3GiuXyq1s';
        }
        my $awssecret = $selected_rows[0]{pri_key};
        return $awssecret;
}


#////////////////////////////////////////////////////////////////////////////

sub stopInstance{
	my $instanceID = $_[0];

	my $EC2_ACCESS_KEY='';
	my $EC2_SECRET_KEY='';
	my $EC2_URL='';
	my $instance_Id = $_[0];
	if ($ENV{'EC2_ACCESS_KEY'}) {
		$EC2_ACCESS_KEY = $ENV{'EC2_ACCESS_KEY'};
	} else {
		#die "EC2_ACCESS_KEY environment variable must be set.";
		$EC2_ACCESS_KEY = getAWSKEY();
	};

	if ($ENV{'EC2_SECRET_KEY'}) {
		$EC2_SECRET_KEY = $ENV{'EC2_SECRET_KEY'};
	} else {
		#die "EC2_SECRET_KEY environment variable must be set.";
		$EC2_SECRET_KEY = getAWSSECRET($EC2_ACCESS_KEY);
	};

	if ($ENV{'EC2_URL'}) {
		$EC2_URL = $ENV{'EC2_URL'};
	} else {
		#die "EC2_URL environment variable must be set.";
		$EC2_URL = 'https://ec2.amazonaws.com/';
	};

	# Pull the host and path out of EC2_URL, since we need them for signing.
	my $EC2_HOST='';
	my $EC2_PATH='';
	if ($EC2_URL =~ /\/\/([^\/]+)(.*)$/) {
		$EC2_HOST = $1;
		if ($2) {
			$EC2_PATH = $2;
		} else {
			$EC2_PATH = "/";
		};
	};
	#undef @actions;
	my @actions;
	my $arg="Action=StopInstances";
	push (@actions, $arg);
	#$instance_Id="i-57423d33";
	$arg="InstanceId=$instance_Id";
	push (@actions, $arg);
	# Generate our timestamp for request signing.

	my $timestamp = generate_timestamp();

	# Add the required variables to complete request signing to the actions list.
	# In the future we should let the user override.

	push (@actions, "SignatureMethod=HmacSHA256", "SignatureVersion=2",
					"Version=2011-05-15", "AWSAccessKeyId=$EC2_ACCESS_KEY",
					"Timestamp=$timestamp");
	#undef @clean_actions;
	my @clean_actions;
	# Process the actions list to escape bad characters in names and values.
	my $x;
	my $y;
	#undef $action;
	my $action;
	foreach $action (@actions) {
		($x,$y) = split(/\=/,$action,2);
		$x = uri_escape_utf8($x);
		$y = uri_escape_utf8($y);
		push (@clean_actions,"$x=$y");
	};

	# Sort them for signing purposes.
	@clean_actions = sort(@clean_actions);

	# Create the query string for signing.
	my $query = join ("&", @clean_actions);

	# Sign the query string.
	my $sig = uri_escape_utf8(hmac_sha256_base64("GET\n$EC2_HOST\n$EC2_PATH\n$query",
						   $EC2_SECRET_KEY));

	# Add the signature to the end of the request url.
	push (@clean_actions,"Signature=$sig=");

	# Re-create the query string with the signature included.
	$query = join ("&", @clean_actions);
#	rnotify($query);
	my $resp = `curl -s \"$EC2_URL?$query\" 2>&1 | xmllint --format -`;
}

initialize();
